﻿///
/// @file PlatformArm64.cpp
/// @brief  ARM64平台相关实现
/// @author shentl
/// @version 2.0
/// @date 2025-04-28
///
#include "PlatformArm64.h"

#include "IntegerType.h"
#include "FloatType.h"

// 寄存器名字，x0-x30，再加sp 64位寄存器名
const std::string PlatformArm64::regName[PlatformArm64::maxRegNum] = {
    "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",  "x8",  "x9",  "x10",
    "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21",
    "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",  "wzr"
};

// 32位寄存器名
const std::string PlatformArm64::regNameW[PlatformArm64::maxRegNum] = {
    "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
    "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
    "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
    "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", "wzr"
};

// 浮点寄存器名
const std::string PlatformArm64::regNameS[PlatformArm64::maxRegNum] = {
    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
    "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
    "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
    "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", "szr"
};

// 整数寄存器数组，全部初始化
RegVariable * PlatformArm64::intRegVal[PlatformArm64::maxRegNum] = {
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[0], 0),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[1], 1),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[2], 2),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[3], 3),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[4], 4),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[5], 5),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[6], 6),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[7], 7),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[8], 8),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[9], 9),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[10], 10),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[11], 11),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[12], 12),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[13], 13),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[14], 14),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[15], 15),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[16], 16),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[17], 17),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[18], 18),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[19], 19),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[20], 20),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[21], 21),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[22], 22),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[23], 23),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[24], 24),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[25], 25),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[26], 26),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[27], 27),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[28], 28),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[29], 29),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[30], 30),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[31], 31),
    new RegVariable(IntegerType::getTypeInt(), PlatformArm64::regName[32], 32),
};

RegVariable * PlatformArm64::floatRegVal[PlatformArm64::maxRegNum] = {
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[0], 0),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[1], 1),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[2], 2),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[3], 3),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[4], 4),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[5], 5),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[6], 6),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[7], 7),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[8], 8),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[9], 9),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[10], 10),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[11], 11),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[12], 12),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[13], 13),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[14], 14),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[15], 15),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[16], 16),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[17], 17),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[18], 18),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[19], 19),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[20], 20),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[21], 21),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[22], 22),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[23], 23),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[24], 24),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[25], 25),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[26], 26),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[27], 27),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[28], 28),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[29], 29),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[30], 30),
    new RegVariable(FloatType::getTypeFloat(), PlatformArm64::regNameS[31], 31),
};

/// @brief 获取零寄存器名称（根据目标寄存器名自动选择wzr/xzr）
/// @param regName 目标寄存器名
/// @return 零寄存器名称
std::string PlatformArm64::getZeroRegName(const std::string & regName)
{
    if (!regName.empty() && regName[0] == 'w')
        return "wzr";
    else
        return "xzr";
}

/// @brief 循环左移两位
void PlatformArm64::roundLeftShiftTwoBit(unsigned int & num)
{
    const unsigned int overFlow = num & 0xc0000000;
    num = (num << 2) | (overFlow >> 30);
}

/// @brief 判断num是否是常数表达式，8位数字循环右移偶数位得到
bool PlatformArm64::__constExpr(int num)
{
    unsigned int new_num = (unsigned int) num;
    for (int i = 0; i < 16; i++) {
        if (new_num <= 0xff) {
            return true;
        }
        roundLeftShiftTwoBit(new_num);
    }
    return false;
}

/// @brief 同时处理正数和负数
bool PlatformArm64::constExpr(int num)
{
    return __constExpr(num) || __constExpr(-num);
}

/// @brief 判定是否是合法的偏移
bool PlatformArm64::isDisp(int num)
{
    return num < 4096 && num > -4096;  // AArch64中常见立即数偏移限制
}

/// @brief 判断是否是合法的寄存器名
bool PlatformArm64::isReg(std::string name)
{
    for (int i = 0; i <= 30; i++) {
        if (name == "x" + std::to_string(i)) return true;
    }
    return name == "sp";
}
